package com.captainkat.asn.calendar;

import android.content.ContentUris;
import android.content.ContentValues;
import android.content.Context;
import android.database.Cursor;
import android.net.Uri;
import android.os.Build;
import android.text.format.DateUtils;

import java.util.ArrayList;
import java.util.Calendar;
import java.util.Iterator;
import java.util.List;
import java.util.TimeZone;

import com.captainkat.asn.bo.CalendarHolder;
import com.captainkat.asn.bo.EventHolder;


public class CalendarManager {
	
	private Uri calendarsUri;
	private Uri eventsUri;
	private Uri instancesUri;
	
	
	private Calendar selectedDate;
	private Calendar midnight;
	private Calendar gmtMidnight;
	
	private TimeZone timeZone;
	
	private List<CalendarHolder> calendarHolder = null;
	private List<EventHolder> eventHolder = null;
	
	private Context applicationContext;
	
	/*** FUNCTION: init: 
	 *   Sets up any values needed by CalendarManager to work with Android Calendar database
	 */
	public void init(Context context) {
		checkVersion();
		timeZone = TimeZone.getDefault();
		selectedDate = Calendar.getInstance(timeZone);
		applicationContext = context;
		
		midnight = Calendar.getInstance();
		midnight.setTimeZone(timeZone);
		midnight.setTime(selectedDate.getTime());
		midnight.set(Calendar.HOUR_OF_DAY, 1);
		midnight.set(Calendar.MINUTE, 0);
		midnight.set(Calendar.SECOND, 0);
		
		gmtMidnight = Calendar.getInstance();
		gmtMidnight.setTimeZone(TimeZone.getTimeZone("GMT"));
		gmtMidnight.setTime(selectedDate.getTime());
		gmtMidnight.set(Calendar.HOUR_OF_DAY, 1);
		gmtMidnight.set(Calendar.MINUTE, 0);
		gmtMidnight.set(Calendar.SECOND, 0);
	}
	
	public EventHolder getEventByIdFromManagedList(String eid) {
		EventHolder e = new EventHolder();
		
		if (this.eventHolder != null) {
			for (Iterator<EventHolder> i = this.eventHolder.iterator(); i.hasNext(); ) {
				e = i.next();
				if (e.getEid().compareTo(eid) == 0)
					return e;
			}

			
		}
		
		return null;
	}
	
	/*** FUNCTION: getEventById 
	 *   Takes an event id in String format
	 *   Returns an EventHolder for that id
	 *   Returns null if event is not found
	 */
	public EventHolder getEventById(String eid) {
		//Build instances uri for ONE DAY STILL NEEDS TIME ZONE?
		Uri.Builder builder  = instancesUri.buildUpon();
		
		//Uri.Builder builder = Uri.parse("content://calendar/instances").buildUpon();


		//make selection and projection
		String[] projection = new String[] {"calendar_id","event_id","title","description" ,"dtstart","dtend","allDay" };
		String selection = "event_id="+eid;
		
		Cursor managedCursor = applicationContext.getContentResolver().query(builder.build(), projection, selection,null,null);
		
		EventHolder e;
		
		if (managedCursor.moveToFirst()) {
			e = new EventHolder();
			
			int calIdColumn = managedCursor.getColumnIndex("calendar_id");
			int startColumn = managedCursor.getColumnIndex("dtstart");
			int titleColumn = managedCursor.getColumnIndex("title");
			int descColumn = managedCursor.getColumnIndex("description");
			int endColumn = managedCursor.getColumnIndex("dtend");
			int allDayColumn = managedCursor.getColumnIndex("allDay");
			
			e.setDtstart(managedCursor.getLong(startColumn));
			e.setDtend(managedCursor.getLong(endColumn));
			e.setCalendarId(managedCursor.getString(calIdColumn));
			e.setTitle(managedCursor.getString(titleColumn));
			e.setDescription(managedCursor.getString(descColumn));
			e.setAllDayEvent(managedCursor.getInt(allDayColumn));
			
			return e;
		}
		
		return null; //if we didn't get the event
	}
	
	/*** FUNCTION: deleteEvent 
	 *   Deletes an event from calendar database
	 */
	public void deleteEvent(EventHolder e) {
		Uri updateEventsUri = ContentUris.withAppendedId(eventsUri, Long.parseLong(e.getEid()));
		
		applicationContext.getContentResolver().delete(updateEventsUri,null,null);
	}
	
	/*** FUNCTION: updateEvent: 
	 *   Updates an event in the calendar database to the values of the passed in EventHolder
	 */
	public void updateEvent(EventHolder e) {
		Uri updateEventsUri = ContentUris.withAppendedId(eventsUri, Long.parseLong(e.getEid()));

		ContentValues event = new ContentValues();
		event.put("calendar_id", e.getCalendarId());
		event.put("title", e.getTitle());
		event.put("description", e.getDescription());
		event.put("allDay", e.getAllDayEvent());
		event.put("dtstart", e.getDtstart());
		event.put("dtend", e.getDtend());


		/*if (e.getAllDayEvent() != 1) { //if it is not all day, put the dates in the content values to insert
			event.put("dtend", e.getDtend());
		} else {
			event.put("dtstart", midnight.getTimeInMillis()+timeZone.getOffset(selectedDate.getTimeInMillis()));
		}*/
		
		applicationContext.getContentResolver().update(updateEventsUri,event,null,null);
	}
	
	/*** FUNCTION: insertEvent: 
	 *   Updates an event in the calendar database to the values of the passed in EventHolder
	 */
	public void insertEvent(EventHolder e) {
		ContentValues event = new ContentValues();
		event.put("calendar_id", e.getCalendarId());
		event.put("title", e.getTitle());
		event.put("description", e.getDescription());
		event.put("allDay", e.getAllDayEvent());
		event.put("dtstart", e.getDtstart());
		event.put("dtend", e.getDtend());

		/*if (e.getAllDayEvent() != 1) { //if it is not all day, put the dates in the content values to insert
			event.put("dtend", e.getDtend());
		} else {
			event.put("dtstart", midnight.getTimeInMillis()+timeZone.getOffset(selectedDate.getTimeInMillis()));
		}*/
		
		applicationContext.getContentResolver().insert(eventsUri,event);
	}

	/*** FUNCTION: getCalendarList: 
	 *   gets the list of available calendars from the database and stores them in the manager
	 *   Returns a List of calendarholder objects
	 */
	public void createCalendarList() {
		calendarHolder = new ArrayList<CalendarHolder>();
		
		try { //in case no databases exists
		
		String[] projection = new String[] {"_id", "name","displayName"};
		Cursor managedCursor = applicationContext.getContentResolver().query(calendarsUri, projection, "selected=1", null, null);
		
		if (managedCursor.moveToFirst()) { //if we found a calendar, find the rest
			
			//get the column indexes for the stuff we need		}
			int nameColumn = managedCursor.getColumnIndex("name");
			int idColumn = managedCursor.getColumnIndex("_id");
			int dispColumn = managedCursor.getColumnIndex("displayName");
			
			CalendarHolder c;
			
			do {
				c = new CalendarHolder();
				c.setName(managedCursor.getString(nameColumn));
				c.setCalendarId(managedCursor.getString(idColumn));
				c.setDisplayName(managedCursor.getString(dispColumn));
				
				calendarHolder.add(c); //add it to the list
			} while (managedCursor.moveToNext());
			
			
		} //end if
		} catch (NullPointerException e) { //In case we don't have access to the database
			//Do something here
		} 
		
	}
	
	/*** FUNCTION: getEventsListForDate: 
	 *   gets the events for the selected date
	 *   Returns a list of EventHolders
	 */
	public void createEventsListforDate(Calendar selectedDate) {
		eventHolder = new ArrayList<EventHolder>();
		
		
		//Build instances uri for ONE DAY STILL NEEDS TIME ZONE?
		Uri.Builder builder = instancesUri.buildUpon();
		long daysofar = ((selectedDate.getTimeInMillis()+timeZone.getOffset(selectedDate.getTimeInMillis())) % DateUtils.DAY_IN_MILLIS);
		long dayleft = DateUtils.DAY_IN_MILLIS - daysofar;
		
		ContentUris.appendId(builder, selectedDate.getTimeInMillis() - daysofar  );
		ContentUris.appendId(builder, selectedDate.getTimeInMillis() + dayleft  );
		
		//make selection and projection
		String[] projection = new String[] {"calendar_id","event_id", "title","dtstart","dtend","allDay","description"};
				//String selection = "Calendars._id="+calendarId;
		try {
			//Query the ContentProvider
			Cursor managedCursor = applicationContext.getContentResolver().query(builder.build(), projection,  null,null,"dtstart ASC, dtend ASC");
			
			EventHolder e; 
			if (managedCursor.moveToFirst()) {
				//get the columns we need
				int calendarIdColumn = managedCursor.getColumnIndex("calendar_id");
				int titleColumn = managedCursor.getColumnIndex("title");
				int idColumn = managedCursor.getColumnIndex("event_id");
				int startColumn = managedCursor.getColumnIndex("dtstart");
				int endColumn = managedCursor.getColumnIndex("dtend");
				int allDayColumn = managedCursor.getColumnIndex("allDay");
				int descColumn = managedCursor.getColumnIndex("description");

				
				//TODO: CHANGE THIS SO THAT YOU CAN HAVE ACCESS TO YOUR ALLDAY EVENTS
				
				do {//set up the event list
					e = new EventHolder();
					e.setCalendarId(managedCursor.getString(calendarIdColumn));
					e.setTitle(managedCursor.getString(titleColumn));
					e.setEid(managedCursor.getString(idColumn));
					e.setDtstart(managedCursor.getLong(startColumn));
					e.setDtend(managedCursor.getLong(endColumn));
					e.setAllDayEvent(managedCursor.getInt(allDayColumn));
					e.setDescription(managedCursor.getString(descColumn));
					
					if (e.getAllDayEvent() == 1) {
						if (e.getDtstart()<=midnight.getTimeInMillis()) {
						eventHolder.add(e);
						}
					} else eventHolder.add(e);

				} while (managedCursor.moveToNext());
				
				
			} //end if
		} catch (NullPointerException e) {
			e.printStackTrace();
		}
		
		
	}
	
	/*** FUNCTION: checkVersion: 
	 *   Checks Android version and selects correct URI
	 */
	public void checkVersion() {
		String calendarURI;
		
		if (Integer.parseInt(Build.VERSION.SDK) <=7) //if lower than or equal to Android 2.1
			calendarURI = "calendar";
		else
			calendarURI = "com.android.calendar";
		
		//put in the correct content provider for that version
		calendarsUri = Uri.parse("content://"+calendarURI+"/calendars");
		eventsUri = Uri.parse("content://"+calendarURI+"/events");
		instancesUri = Uri.parse("content://"+calendarURI+"/instances/when");
	}

	public Calendar getSelectedDate() {
		return selectedDate;
	}

	public void setSelectedDate(Calendar selectedDate) {
		this.selectedDate = selectedDate;
	}

	public List<CalendarHolder> getCalendarHolder() {
		return calendarHolder;
	}

	public void setCalendarHolder(List<CalendarHolder> calendarHolder) {
		this.calendarHolder = calendarHolder;
	}

	public List<EventHolder> getEventHolder() {
		return eventHolder;
	}

	public void setEventHolder(List<EventHolder> eventHolder) {
		this.eventHolder = eventHolder;
	}
	
}


